<?php
class Image {
    const SESS_CAPTCHA = 'captcha';
    private static $captchaLife = 86400;
    public static function getCaptcha($imgWidth, $imgHeight,$charLen=5, $outputDir='') {
        if ($outputDir) {
            $imgDir = $outputDir . '/' . $imgWidth . '_' . $imgHeight;
            if(false == is_dir($imgDir) && false == @mkdir($imgDir, 0777, true)) {
                throw new Exception('图片输出目录"' . $imgDir . '"不存在，且创建失败,请手工创建，并设置目录为可写');
            }
            @chdir($imgDir);
            $captchaArray = glob('*.gif');
            if (sizeof($captchaArray) < 3000) {
                return self::makeCaptcha($imgWidth, $imgHeight,$charLen, $imgDir);
            } else {
                $index = mt_rand(0,2999);
                $captchaFile = $captchaArray[$index];
                $sessValue = basename($captchaFile, '.gif');
                if(strlen($sessValue) == $charLen) {
                    Session::set(self::SESS_CAPTCHA, $sessValue);
                    return $captchaFile;
                }
            }
        }
        return self::makeCaptcha($imgWidth, $imgHeight,$charLen, $imgDir);
    }
    
    private static function makeCaptcha($imgWidth, $imgHeight, $charLen, $imgDir='') {
        $chars = array('3', '7', '8', 'B', 'C', 'D', 'E', 'F', 'H', 'J',
                       'K', 'M', 'P', 'Q', 'R', 'S', 'T', 'W', 'X', 'Y');
        shuffle($chars);
        $chunkArray = array_chunk($chars, $charLen);
        $sessArray = $chunkArray[0];
        $sessValue = implode('', $sessArray);
        Session::set(self::SESS_CAPTCHA, $sessValue);
        $imageFile = '';
        if($imgDir) {
            $imgFile = $imgDir . '/' . $sessValue . '.gif';
            if (file_exists($imgFile)) {
                $modiTime = filemtime($imgFile);
                if (time() - $modiTime < self::$captchaLife) {
                    return $imgFile;
                }
            }
        }
        $fontFile = dirname(__FILE__) . '/comic.ttf';
        $im = imagecreatetruecolor($imgWidth, $imgHeight);
        $randColor = mt_rand(200,240);
        $bgColor = imagecolorallocate($im, $randColor, $randColor, $randColor);
        imagefilledrectangle($im, 0, 0, $imgWidth, $imgHeight, $bgColor);
        $fontSize = intval($imgHeight / 1.5);
        $angleArray = array();
        $totalWidth =2;
        $lastAngle = 0;
        foreach($sessArray as $char) {
            $angle = mt_rand(0, 30);
            if($angle > 15) $angle = 15 - $angle;
            #如果前一个字符顺时针旋转，而当前字符逆时针旋转时容易重叠
            #if($lastAngle <0 && $angle >0) $angle = 0;
            $box = imagettfbbox($fontSize, $angle, $fontFile, $char);
            $charWidth = $angle < 0 ? abs($box[0] - $box[4]) : abs($box[6]-$box[2]);
            $charHeight = $angle < 0 ? abs($box[7] - $box[3]) : abs($box[5] - $box[1]);
            $maxHeight = $maxHeight > $charHeight ? $maxHeight : $charHeight;
            $box = imagettfbbox($fontSize, 0, $fontFile, $char);
            $radian = deg2rad($angle);
            $charOffsetX = intval(abs($box[7]) * sin($radian));
            $charOffsetY = intval(abs($box[2]) * sin($radian));
            $angleArray[$char] = array($angle, $totalWidth, $charHeight, $charOffsetX, $charOffsetY, $charWidth, $charHeight);
            $totalWidth += $charWidth;
        }
        if ($totalWidth > $imgWidth)
            $fontSize = $fontSize-1;
        else if($maxHeight > $imgHeight)
            $fontSize = $fontSize -1;
        $startX = intval(($imgWidth - $totalWidth) / 2);
        if ($startX < 0) $startX = 1;
        foreach($sessArray as $char) {
            $color = imagecolorallocate($im, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120));
            imagettftext($im, $fontSize, $angleArray[$char][0], $startX + $angleArray[$char][1] + $angleArray[$char][3], $imgHeight - 5 + $angleArray[$char][4], $color, $fontFile, $char);
        }
        for ($i=0; $i<5; $i++) {
            $color = imagecolorallocate($im, mt_rand(0,255), mt_rand(0,255), mt_rand(0,255));
            imageline($im, mt_rand(0, intval($imgWidth/2)), mt_rand(0, $imgHeight), mt_rand(intval($imgWidth/2), $imgWidth), mt_rand(0, $imgHeight), $color);
        }
        if($imgDir) imagegif($im, $imgFile);
        else imagegif($im);

        imagedestroy($im);
        return $imgFile;
    }
    
    public static function checkCaptcha($inputValue) {
        return strtolower($inputValue) == strtolower(Session::get(self::SESS_CAPTCHA));
    }
}
?>